bitkeeper revision 1.1159.187.48 (41adc6420WlNaaoUkvfgNxl44rpYYg)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 1 Dec 2004 13:25:22 +0000 (13:25 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 1 Dec 2004 13:25:22 +0000 (13:25 +0000)
Export Xen s/w perfctrs to DOM0 via new 'xenperf' utility.

.rootkeys
BitKeeper/etc/ignore
tools/libxc/xc.h
tools/libxc/xc_misc.c
tools/misc/Makefile
tools/misc/xenperf.c [new file with mode: 0644]
xen/arch/x86/memory.c
xen/common/dom0_ops.c
xen/common/perfc.c
xen/include/public/dom0_ops.h

index 1691f867c4f7633ad5a399317f30408d0df2a687..31497b58ac63388125e6d421654f7de88b8ce15c 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README
 405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons
 40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend
+41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/misc/xenperf.c
 4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
 4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops
 40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
index ec7c4e8ee613bbe7ed73fd7fa8747091faecd6ad..6767868bd3a543c0d79f140ba01a366fde702588 100644 (file)
@@ -58,7 +58,7 @@ tools/balloon/balloon
 tools/check/.*
 tools/libxc/xen/*
 tools/misc/miniterm/miniterm
-tools/misc/xen_cpuperf
+tools/misc/xenperf
 tools/vnet/gc
 tools/vnet/gc*/*
 tools/vnet/vnet-module/.tmp_versions/*
index 7778b71673e5fbbcac570295ed2c389e45fc9fd2..18665e917810dd4bac019e02eef08209be34a550 100644 (file)
@@ -178,14 +178,19 @@ int xc_domain_setinitialmem(int xc_handle,
                             unsigned int initial_memkb);
 
 int xc_domain_setmaxmem(int xc_handle,
-                            u32 domid, 
-                            unsigned int max_memkb);
+                        u32 domid, 
+                        unsigned int max_memkb);
 
 int xc_domain_setvmassist(int xc_handle,
                           u32 domid, 
                           unsigned int cmd,
                           unsigned int type);
 
+typedef dom0_perfc_desc_t xc_perfc_desc_t;
+/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
+int xc_perfc_control(int xc_handle,
+                     u32 op,
+                     xc_perfc_desc_t *desc);
 
 void *xc_map_foreign_range(int xc_handle, u32 dom,
                             int size, int prot,
index e8ea18c5ff388c8253eb660d1f8dce1e82b9285d..0efd1f1972ff15de3e8df146aa23341a386b613e 100644 (file)
@@ -74,10 +74,26 @@ int xc_sched_id(int xc_handle,
     op.cmd = DOM0_SCHED_ID;
     op.interface_version = DOM0_INTERFACE_VERSION;
     
-    if((ret = do_dom0_op(xc_handle, &op))) return ret;
+    if ( (ret = do_dom0_op(xc_handle, &op)) != 0 )
+        return ret;
     
     *sched_id = op.u.sched_id.sched_id;
     
     return 0;
 }
 
+int xc_perfc_control(int xc_handle,
+                     u32 op,
+                     xc_perfc_desc_t *desc)
+{
+    int rc;
+    dom0_op_t dop;
+
+    dop.cmd = DOM0_PERFCCONTROL;
+    dop.u.perfccontrol.op   = op;
+    dop.u.perfccontrol.desc = desc;
+
+    rc = do_dom0_op(xc_handle, &dop);
+
+    return (rc == 0) ? dop.u.perfccontrol.nr_counters : rc;
+}
index 760348b0b4c83769cd42248736a1023b180bbb37..7c20e8d1b03180bff28dc3775b6f3d917b0fe99b 100644 (file)
@@ -3,22 +3,18 @@ XEN_ROOT=../..
 include $(XEN_ROOT)/tools/Make.defs
 
 CC         = gcc
-CFLAGS     = -Wall -O3 
+CFLAGS     = -Wall -Werror -O3 
 
 INCLUDES += -I $(XEN_XC)
 INCLUDES += -I $(XEN_LIBXC)
-INCLUDES += -I $(XEN_LIBXUTIL)
-
-CFLAGS += $(INCLUDES)
+CFLAGS   += $(INCLUDES)
 
 HDRS     = $(wildcard *.h)
-SRCS     = $(wildcard *.c)
-OBJS     = $(patsubst %.c,%.o,$(SRCS))
 
-TARGETS  = 
+TARGETS  = xenperf
 
 INSTALL_BIN  = $(TARGETS) xencons
-INSTALL_SBIN = netfix xm xend xensv
+INSTALL_SBIN = netfix xm xend xensv xenperf
 
 all: $(TARGETS)
        $(MAKE) -C miniterm
@@ -32,7 +28,7 @@ install: all
 
 clean:
        $(RM) *.o $(TARGETS) *~
-       $(MAKE) -C miniterm clean       
+       $(MAKE) -C miniterm clean
 
 %: %.c $(HDRS) Makefile
-       $(CC) $(CFLAGS) -o $@ $<
+       $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxc -L$(XEN_LIBXUTIL) -lxutil
diff --git a/tools/misc/xenperf.c b/tools/misc/xenperf.c
new file mode 100644 (file)
index 0000000..d284622
--- /dev/null
@@ -0,0 +1,104 @@
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ *        File: xenperf.c
+ *      Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
+ *        Date: Nov 2004
+ * 
+ * Description: 
+ */
+
+
+#include <xc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+    int              i, j, xc_handle;
+    xc_perfc_desc_t *pcd;
+    unsigned int     num, sum, reset = 0;
+
+    if ( argc > 1 )
+    {
+        char *p = argv[1];
+        if ( (*p++ == '-')  && (*p == 'r') )
+            reset = 1;
+        else
+        {
+            printf("%s: [-r]\n", argv[0]);
+            printf("no args: print xen performance counters\n");
+            printf("    -r : reset xen performance counters\n");
+            return 0;
+        }
+    }   
+
+    if ( (xc_handle = xc_interface_open()) == -1 )
+    {
+        fprintf(stderr, "Error opening xc interface: %d (%s)\n",
+                errno, strerror(errno));
+        return 1;
+    }
+    
+    if ( reset )
+    {
+        if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_RESET,
+                              NULL) < 0 )
+        {
+            fprintf(stderr, "Error reseting performance counters: %d (%s)\n",
+                    errno, strerror(errno));
+            return 1;
+        }
+
+        return 0;
+    }
+
+
+    if ( (num = xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
+                                 NULL)) < 0 )
+    {
+        fprintf(stderr, "Error getting number of perf counters: %d (%s)\n",
+                errno, strerror(errno));
+        return 1;
+    }
+
+    pcd = malloc(sizeof(*pcd) * num);
+
+    if ( mlock(pcd, sizeof(*pcd) * num) != 0 )
+    {
+        fprintf(stderr, "Could not mlock descriptor buffer: %d (%s)\n",
+                errno, strerror(errno));
+        exit(-1);
+    }
+
+    if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, pcd) <= 0 )
+    {
+        fprintf(stderr, "Error getting perf counter description: %d (%s)\n",
+                errno, strerror(errno));
+        return 1;
+    }
+
+    munlock(pcd, sizeof(*pcd) * num);
+
+    for ( i = 0; i < num; i++ )
+    {
+        printf ("%-35s ", pcd[i].name);
+        
+        sum = 0;
+        for ( j = 0; j < pcd[i].nr_vals; j++ )
+            sum += pcd[i].vals[j];
+        printf ("T=%10u ", (unsigned int)sum);
+
+        for ( j = 0; j < pcd[i].nr_vals; j++ )
+            printf(" %10u", (unsigned int)pcd[i].vals[j]);
+
+        printf("\n");
+    }
+
+    return 0;
+}
index 5734f45ba95c2ebbd21420bdc60a9ead85e7a205..7cab825a4d397f581d3fdc22920e3b6155086a84 100644 (file)
@@ -1299,9 +1299,6 @@ int do_mmu_update(
     u32 type_info;
     domid_t domid;
 
-    perfc_incrc(calls_to_mmu_update); 
-    perfc_addc(num_page_updates, count);
-
     cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
 
     /*
@@ -1331,6 +1328,9 @@ int do_mmu_update(
         }
     }
 
+    perfc_incrc(calls_to_mmu_update); 
+    perfc_addc(num_page_updates, count);
+
     if ( unlikely(!array_access_ok(VERIFY_READ, ureqs, count, sizeof(req))) )
     {
         rc = -EFAULT;
index 812814068b84d3049fc1ffef715d8d34baba6803..5622ae174e7c8ce223151d4cd996f433aeda65d0 100644 (file)
@@ -651,6 +651,16 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     }
     break;
 
+#ifdef PERF_COUNTERS
+    case DOM0_PERFCCONTROL:
+    {
+        extern int perfc_control(dom0_perfccontrol_t *);
+        ret = perfc_control(&op->u.perfccontrol);
+        copy_to_user(u_dom0_op, op, sizeof(*op));
+    }
+    break;
+#endif
+
     default:
         ret = arch_do_dom0_op(op,u_dom0_op);
 
index 3a05c2e0719539e844e5dac2ef93b289ad4f3b18..d5384c4af5a39d0456be2212d56f1df0bcc35964 100644 (file)
@@ -4,6 +4,8 @@
 #include <xen/time.h>
 #include <xen/perfc.h>
 #include <xen/keyhandler.h> 
+#include <public/dom0_ops.h>
+#include <asm/uaccess.h>
 
 #undef  PERFCOUNTER
 #undef  PERFCOUNTER_CPU
@@ -79,8 +81,9 @@ void perfc_reset(unsigned char key)
     s_time_t now = NOW();
     atomic_t *counters = (atomic_t *)&perfcounters;
 
-    printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
-           (u32)(now>>32), (u32)now);
+    if ( key != '\0' )
+        printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
+               (u32)(now>>32), (u32)now);
 
     /* leave STATUS counters alone -- don't reset */
 
@@ -109,3 +112,107 @@ void perfc_reset(unsigned char key)
     }
 }
 
+static dom0_perfc_desc_t perfc_d[NR_PERFCTRS];
+static int               perfc_init = 0;
+static int perfc_copy_info(dom0_perfc_desc_t *desc)
+{
+    unsigned int i, j;
+    atomic_t *counters = (atomic_t *)&perfcounters;
+
+    if ( desc == NULL )
+        return 0;
+
+    /* We only copy the name and array-size information once. */
+    if ( !perfc_init ) 
+    {
+        for ( i = 0; i < NR_PERFCTRS; i++ )
+        {
+            strncpy(perfc_d[i].name, perfc_info[i].name,
+                    sizeof(perfc_d[i].name));
+            perfc_d[i].name[sizeof(perfc_d[i].name)-1] = '\0';
+
+            switch ( perfc_info[i].type )
+            {
+            case TYPE_SINGLE:
+            case TYPE_S_SINGLE:
+                perfc_d[i].nr_vals = 1;
+                break;
+            case TYPE_CPU:
+            case TYPE_S_CPU:
+                perfc_d[i].nr_vals = smp_num_cpus;
+                break;
+            case TYPE_ARRAY:
+            case TYPE_S_ARRAY:
+                perfc_d[i].nr_vals = perfc_info[i].nr_elements;
+                break;
+            }
+
+            if ( perfc_d[i].nr_vals > ARRAY_SIZE(perfc_d[i].vals) )
+                perfc_d[i].nr_vals = ARRAY_SIZE(perfc_d[i].vals);
+        }
+
+        perfc_init = 1;
+    }
+
+    /* We gather the counts together every time. */
+    for ( i = 0; i < NR_PERFCTRS; i++ )
+    {
+        switch ( perfc_info[i].type )
+        {
+        case TYPE_SINGLE:
+        case TYPE_S_SINGLE:
+            perfc_d[i].vals[0] = atomic_read(&counters[0]);
+            counters += 1;
+            break;
+        case TYPE_CPU:
+        case TYPE_S_CPU:
+            for ( j = 0; j < perfc_d[i].nr_vals; j++ )
+                perfc_d[i].vals[j] = atomic_read(&counters[j]);
+            counters += NR_CPUS;
+            break;
+        case TYPE_ARRAY:
+        case TYPE_S_ARRAY:
+            for ( j = 0; j < perfc_d[i].nr_vals; j++ )
+                perfc_d[i].vals[j] = atomic_read(&counters[j]);
+            counters += perfc_info[i].nr_elements;
+            break;
+        }
+    }
+
+    return (copy_to_user(desc, perfc_d, NR_PERFCTRS * sizeof(*desc)) ?
+            -EFAULT : 0);
+}
+
+/* Dom0 control of perf counters */
+int perfc_control(dom0_perfccontrol_t *pc)
+{
+    static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+    u32 op = pc->op;
+    int rc;
+
+    pc->nr_counters = NR_PERFCTRS;
+
+    spin_lock(&lock);
+
+    switch ( op )
+    {
+    case DOM0_PERFCCONTROL_OP_RESET:
+        perfc_copy_info(pc->desc);
+        perfc_reset(0);
+        rc = 0;
+        break;
+
+    case DOM0_PERFCCONTROL_OP_QUERY:
+        perfc_copy_info(pc->desc);
+        rc = 0;
+        break;
+
+    default:
+        rc = -EINVAL;
+        break;
+    }
+
+    spin_unlock(&lock);
+
+    return rc;
+}
index f8c7bab6d31206aa3ac82bff1bb949fd3c807903..9673c886785dd5c2f52fb3e42230687755401783 100644 (file)
@@ -386,6 +386,25 @@ typedef struct {
     u32      __pad1;
 } PACKED dom0_read_memtype_t; /* 32 bytes */
 
+/* Interface for controlling Xen software performance counters. */
+#define DOM0_PERFCCONTROL        34
+/* Sub-operations: */
+#define DOM0_PERFCCONTROL_OP_RESET 1   /* Reset all counters to zero. */
+#define DOM0_PERFCCONTROL_OP_QUERY 2   /* Get perfctr information. */
+typedef struct {
+    u8      name[80];               /*  0: name of perf counter */
+    u32     nr_vals;                /* 80: number of values for this counter */
+    u32     vals[64];               /* 84: array of values */
+} PACKED dom0_perfc_desc_t; /* 340 bytes */
+typedef struct {
+    /* IN variables. */
+    u32            op;                /*  0: DOM0_PERFCCONTROL_OP_??? */
+    /* OUT variables. */
+    u32            nr_counters;       /*  4: number of counters */
+    dom0_perfc_desc_t *desc;          /*  8: counter information (or NULL) */
+    MEMORY_PADDING;
+} PACKED dom0_perfccontrol_t; /* 16 bytes */
+
 typedef struct {
     u32 cmd;                          /* 0 */
     u32 interface_version;            /* 4 */ /* DOM0_INTERFACE_VERSION */
@@ -419,6 +438,7 @@ typedef struct {
         dom0_add_memtype_t       add_memtype;
         dom0_del_memtype_t       del_memtype;
         dom0_read_memtype_t      read_memtype;
+        dom0_perfccontrol_t      perfccontrol;
     } PACKED u;
 } PACKED dom0_op_t; /* 80 bytes */